#pragma once

#include <qbmessage/include/message_sync.h>
#include <qbnet/include/network_service.h>
#include <string.h>

#include <string>

#include "../auth.h"
#include "task_group.h"

namespace qb {
class S_AUTH_EXPORT CAuthLogin : public IMessageSyncObserver,
                                 public ITaskGroupObserver,
                                 public INetworkServiceObserver {
 public:
  static CAuthLogin& instance();

  int32_t destory();

  int32_t login();
  int32_t reLogin();
  int32_t manualReLogin();
  bool isLoginning();
  bool isLogined();
  bool isReLogin();
  int32_t logout();

  // IMessageSyncObserver
  STDMETHOD_(void, OnNetData)(char* pRecvData, int nDataLen);
  STDMETHOD_(void, OnNetStatus)(int status);

  // INetworkServiceObserver
  STDMETHOD_(bool, OnConnect)(THIS_ int32_t connect_id, int32_t error_id) {
    return false;
  }
  STDMETHOD_(void, OnReceive)
  (THIS_ int32_t connect_id, MESSAGE_SHARED_PTR msp) {}
  STDMETHOD_(void, OnReceive2)
  (THIS_ int32_t connect_id, const char* buff, uint32_t bytes) {}
  STDMETHOD_(void, OnFailed)(THIS_ int32_t connect_id, int32_t error_id);

 protected:
  // ITaskGroupObserver
  virtual void OnTaskStep(qb::NetStatus uStep, short ret_code);
  virtual void OnAllTaskFinished();
  virtual void OnTaskGroupFailed(qb::NetStatus uStep, short ret_code);

  void OnRecvMsg(char* pData, int nDataLen);
  void OnRecvNetStauts(int32_t status);
  void CloseConnect();

  void startReLoginTimer(std::function<void()> task);
  void stopReLoginTimer();
  void onTimer();

 private:
  CAuthLogin();
  virtual ~CAuthLogin();

 private:
  CTaskGroup m_TaskGroup;

  std::string m_strServerIP;
  std::string m_strServerPort;
  std::string m_strGatewayIP;
  std::string m_strGatewayPort;

  std::atomic<bool> m_expired;
  std::atomic<bool> m_try_to_expire;
  std::mutex m_mutex;
  std::condition_variable m_expired_cond;

  static int sReloginTime[];
};
}  // namespace qb
